package com.kly.user.serviceImpl;

import com.alibaba.fastjson.JSONObject;
import com.alibaba.nacos.api.config.annotation.NacosValue;
import com.fqgj.common.api.Response;
import com.fqgj.common.utils.CollectionUtils;
import com.google.common.base.Splitter;
import com.google.common.collect.Lists;
import com.kly.user.constant.RedisKey;
import com.kly.user.db.dao.UserDao;
import com.kly.user.db.entity.UserEntity;
import com.kly.user.enums.AppCodeEnum;
import com.kly.user.enums.RememberTime;
import com.kly.user.service.WhiteListService;
import com.kly.user.utils.RedisService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

@Slf4j
@Service("whiteListService")
public class WhiteListServiceImpl implements WhiteListService {

    @Resource
    private UserDao userDao;

    @NacosValue(value = "${meboo.white.list}", autoRefreshed = true)
    private String mebboWhiteList;

    @NacosValue(value = "${pp.white.list}", autoRefreshed = true)
    private String ppWhiteList;

    /**
     * 当版本与redis中不一致时，需要重新加载数据到缓存中
     */
    @NacosValue(value = "${white.list.version:1}", autoRefreshed = true)
    private String whiteVersion;

    @Resource
    RedisService redisService;


    @Override
    public Response<Boolean> in(String appCode, String userCode, String mobile, String email) {
        boolean result = false;
        log.info("WhiteListService:in starts. {},{},{},{}", appCode, userCode, mobile, email);
        if (AppCodeEnum.MEBOO.getAppCode().equals(appCode)) {
            result = check(userCode, mobile, email, mebboWhiteList);
        }
        if (AppCodeEnum.PP.getAppCode().equals(appCode)) {
            result = check(userCode, mobile, email, ppWhiteList);
        }
        log.info("WhiteListService:in ends. {},{},{},{},{}", appCode, userCode, mobile, email, result);
        return Response.ok(result);
    }

    @Override
    public Response<List<String>> userCodeList() {
        // todo 缓存白名单用户userCodeList，并且根据白名单变化更新缓存
//        List<String> list = userCodeList(AppCodeEnum.MEBOO.getAppCode(), mebboWhiteList);
//        list.addAll(userCodeList(AppCodeEnum.PP.getAppCode(), ppWhiteList));
//        log.info("====白名单用户1：{}", JSONObject.toJSONString(list));

        final ArrayList<String> allWhiteUsers = Lists.newArrayList();
        if (StringUtils.isNotBlank(mebboWhiteList)) {
            allWhiteUsers.addAll(Splitter.on(",").splitToList(mebboWhiteList));
        }
        if (StringUtils.isNotBlank(ppWhiteList)) {
            allWhiteUsers.addAll(Splitter.on(",").splitToList(ppWhiteList));
        }

        final List<String> allUserCodes = listAllWhiteUsers(allWhiteUsers);
        log.info("====白名单用户：{}", JSONObject.toJSONString(allUserCodes));


        return Response.ok(allUserCodes);
    }

    private List<String> listAllWhiteUsers(ArrayList<String> allWhiteUsers) {

        // 白名单版本控制，配置中的版本号与缓存中不一致时，需要重新加载白名单数据
        final String versionNum = redisService.getString(RedisKey.USER_WHITE_LIST_VERSION);
        if (StringUtils.isNotBlank(versionNum)) {
            if (!versionNum.equals(whiteVersion)) {
                redisService.del(RedisKey.USER_WHITE_LIST);
            }
        } else {
            redisService.setString(RedisKey.USER_WHITE_LIST_VERSION, whiteVersion);
            redisService.del(RedisKey.USER_WHITE_LIST);
        }

        final Map<String, String> allUser = redisService.hGetAll(RedisKey.USER_WHITE_LIST);
        if (CollectionUtils.isNotEmpty(allUser)) {
            return new ArrayList<>(allUser.keySet());
        }

        final List<UserEntity> userEntities = userDao.listAllWhiteUsers(allWhiteUsers);
        if (CollectionUtils.isNotEmpty(userEntities)) {
            for (UserEntity user : userEntities) {
                redisService.hPut(RedisKey.USER_WHITE_LIST, user.getUserCode(), String.valueOf(System.currentTimeMillis()));
                redisService.expire(RedisKey.USER_WHITE_LIST, (int) RememberTime.ONE_HOURS.getTime(), user.getUserCode());
            }
        }
        redisService.setString(RedisKey.USER_WHITE_LIST_VERSION, whiteVersion);
        return Lists.newArrayList();
    }

    private List<String> userCodeList(String appCode, String whiteList) {
        List<String> list = Arrays.stream(whiteList.split(",")).collect(Collectors.toList());
        return list.stream().map(item -> getUserCode(appCode, item)).collect(Collectors.toList());
    }

    private String getUserCode(String appCode, String identity) {
        log.info("WhiteListService:getUserCode starts. {}, {}", appCode, identity);
        UserEntity user = userDao.selectOne(appCode, identity);
        log.info("WhiteListService:getUserCode ends. {}", user != null);
        return user != null ? user.getUserCode() : "";
    }

    private boolean check(String userCode, String mobile, String email, String whiteList) {
        if (StringUtils.isNotBlank(userCode) && whiteList.contains(userCode)) {
            return true;
        }
        if (StringUtils.isNotBlank(mobile) && whiteList.contains(mobile)) {
            return true;
        }
        return StringUtils.isNotBlank(email) && whiteList.contains(email);
    }
}
